using System.Net;
using Xunit;
using SmartSite.Network;
using SmartSite.Network.Test;

namespace SmartSite.Frame.Test
{
    public class TestRestoreFrame
    {
        [Fact]
        public void TestOnRestored()
        {
            //Given
            RestoreFrameController operating = new RestoreFrameController();
            BaseFrame frame = new BaseFrame();
            frame.CRC.Value = frame.CalculationCRC();
            SocketStateEventArgs state = new SocketStateEventArgs(
                new AsyncSocketStub(),
                new IPEndPoint(IPAddress.Any, 0),
                frame.Buffer.ToArray()
            );

            //When

            //Then
            Assert.Raises<RestoredData>(
                (h) => operating.RestoreFrame.Restored += h,
                (h) => operating.RestoreFrame.Restored -= h,
                () => operating.Restore(state));
        }


        // 测试异常：协议版本错误
        [Theory]
        [InlineData(0)]
        [InlineData(3)]
        [InlineData(5)]
        [InlineData(15)]
        public void TestProtoclVersionError(ushort protocolVersion)
        {
            //Given
            RestoreFrameController operating = new RestoreFrameController();
            BaseFrame frame = new BaseFrame();

            //When
            frame.ProtocolVersion.Value = protocolVersion;
            frame.CRC.Value = frame.CalculationCRC();
            SocketStateEventArgs state = new SocketStateEventArgs(
                new AsyncSocketStub(),
                new IPEndPoint(IPAddress.Any, 0),
                frame.Buffer.ToArray()
            );

            //Then
            Assert.Raises<SocketStateEventArgs>(
                (h) => operating.RestoreFrame.ProtocolVersionError += h,
                (h) => operating.RestoreFrame.ProtocolVersionError -= h,
                () => operating.Restore(state));
        }

        // 测试异常：协议版本错误
        [Theory]
        [InlineData(0)]
        [InlineData(3)]
        [InlineData(5)]
        [InlineData(15)]
        public void TestFactoryCodeError(ushort factoryCode)
        {
            //Given
            RestoreFrameController operating = new RestoreFrameController();
            BaseFrame frame = new BaseFrame();

            //When
            frame.FactoryCode.Value = factoryCode;
            frame.CRC.Value = frame.CalculationCRC();
            SocketStateEventArgs state = new SocketStateEventArgs(
                new AsyncSocketStub(),
                new IPEndPoint(IPAddress.Any, 0),
                frame.Buffer.ToArray()
            );

            //Then
            Assert.Raises<SocketStateEventArgs>(
                (h) => operating.RestoreFrame.FactoryCodeError += h,
                (h) => operating.RestoreFrame.FactoryCodeError -= h,
                () => operating.Restore(state));
        }

        // 测试异常: 帧类型
        [Theory]
        [InlineData(21)]
        public void TestFrameTypeError(byte frameType)
        {
            //Given
            RestoreFrameController operating = new RestoreFrameController();
            BaseFrame frame = new BaseFrame();

            //When
            frame.FrameType.Value = (FrameTypeEnum)frameType;
            frame.CRC.Value = frame.CalculationCRC();
            SocketStateEventArgs state = new SocketStateEventArgs(
                new AsyncSocketStub(),
                new IPEndPoint(IPAddress.Any, 0),
                frame.Buffer.ToArray()
            );

            //Then
            Assert.Raises<SocketStateEventArgs>(
                (h) => operating.RestoreFrame.FrameTypeError += h,
                (h) => operating.RestoreFrame.FrameTypeError -= h,
                () => operating.Restore(state));
        }


        /**
         * 测试异常: 空buffer
         */
        [Fact]
        public void TestUnknowFrameForNullBuffer()
        {
            //Given
            RestoreFrameController operating = new RestoreFrameController();
            BaseFrame frame = new BaseFrame();

            //When
            SocketStateEventArgs state = new SocketStateEventArgs(
                new AsyncSocketStub(),
                new IPEndPoint(IPAddress.Any, 0),
                new byte[0]
            );

            //Then
            Assert.Raises<SocketStateEventArgs>(
                (h) => operating.RestoreFrame.UnknowFrameError += h,
                (h) => operating.RestoreFrame.UnknowFrameError -= h,
                () => operating.Restore(state));
        }

        // 测试异常: 短buffer
        [Fact]
        public void TestUnknowFrameForShortBuffer()
        {
            //Given
            RestoreFrameController operating = new RestoreFrameController();
            BaseFrame frame = new BaseFrame();

            //When
            SocketStateEventArgs state = new SocketStateEventArgs(
                new AsyncSocketStub(),
                new IPEndPoint(IPAddress.Any, 0),
                new byte[frame.Buffer.Count - 1]
            );

            //Then
            Assert.Raises<SocketStateEventArgs>(
                (h) => operating.RestoreFrame.UnknowFrameError += h,
                (h) => operating.RestoreFrame.UnknowFrameError -= h,
                () => operating.Restore(state));
        }

        // 测试异常：Crc校验错误
        [Theory]
        [InlineData(0)]
        [InlineData(0xFFFF)]
        public void TestCrcError(ushort crc)
        {
            //Given
            RestoreFrameController operating = new RestoreFrameController();
            BaseFrame frame = new BaseFrame();

            //When
            frame.CRC.Value = crc;
            SocketStateEventArgs state = new SocketStateEventArgs(
                new AsyncSocketStub(),
                new IPEndPoint(IPAddress.Any, 0),
                frame.Buffer.ToArray()
            );

            //Then
            Assert.Raises<SocketStateEventArgs>(
                (h) => operating.RestoreFrame.CrcError += h,
                (h) => operating.RestoreFrame.CrcError -= h,
                () => operating.Restore(state));
        }
    }
}